package cn.krui.helper.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;

import org.springframework.util.StringUtils;

import cn.krui.helper.bean.SysLoginInfo;
import cn.krui.helper.tools.CodeUtils;
import cn.krui.helper.tools.JsonUtils;
import cn.krui.helper.tools.RedisUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author zc
 */
public class TokenFilter implements Filter {
    public static final String PARAM_NAME_EXCLUSIONS = "EXCEPTION_URI";
    public static final String PARAM_NAME_EXCEPTION_TOKEN = "EXCEPTION_TOKEN_URI";
    private Set<String> excludesPattern;
    private Set<String> excludesTokenPattern;
    protected ServletPathMatcher pathMatcher = new ServletPathMatcher(); 
    private RedisUtils rUtils; 
    public TokenFilter(RedisUtils _Utils){
        rUtils = _Utils;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String param = filterConfig.getInitParameter(PARAM_NAME_EXCLUSIONS);
        if (param != null && param.trim().length() != 0) {
            this.excludesPattern = new HashSet<>(Arrays.asList(param.split(",")));
        }
        param = filterConfig.getInitParameter(PARAM_NAME_EXCEPTION_TOKEN);
        if (param != null && param.trim().length() != 0) {
            this.excludesTokenPattern = new HashSet<>(Arrays.asList(param.split(",")));
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        if(httpRequest.getMethod().equals("OPTIONS")){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        String requestURI = httpRequest.getRequestURI();
        // 超级权限
        String _super = httpRequest.getHeader("super");
        if(!StringUtils.isEmpty(_super) && _super.equals("mq")){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        // 全局验证是否排除
        if (this.isExclusion(requestURI, this.excludesPattern)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            // 验证是否需要token
            String token = httpRequest.getHeader("token");
            if (StringUtils.isEmpty(token)) {
                Map<String, Object> data = new HashMap<>();
                data.put("code", CodeUtils.PERMISSSION_OUT);
                servletRequest.setAttribute("data", data);
                servletRequest.getRequestDispatcher("/actuator/printf").forward(servletRequest, servletResponse);
                return;
            }
            String loginInfo = rUtils.get("login_token:"+token); 
            if(StringUtils.isEmpty(loginInfo)){
                Map<String, Object> data = new HashMap<>();
                data.put("code", CodeUtils.LOGIN_TIMEOUT);
                servletRequest.setAttribute("data", data);
                servletRequest.getRequestDispatcher("/actuator/printf").forward(servletRequest, servletResponse);
                return;
            }
            if (this.isExclusion(requestURI, this.excludesTokenPattern)) {
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                // 需要验证权限
                SysLoginInfo _sysLoginInfo = JsonUtils.toObject(loginInfo.toString(),SysLoginInfo.class);
                Map<String,String> _role_permissions_map = _sysLoginInfo.getRole_permissions_map();
                Boolean bool_uri = false;
                if(_role_permissions_map!=null){
                    //按模块校验
                    int first = requestURI.indexOf("/", 0); 
                    int second = requestURI.indexOf("/", first+1);
                    String _role_permissions = "";
                    if (first == -1 || second == -1) {
                        _role_permissions = _role_permissions_map.get("");
                    }
                    else{
                        String module = requestURI.substring(first+1, second);
                        _role_permissions = _role_permissions_map.get(module);
                    }
                    if (StringUtils.isEmpty(_role_permissions)) {
                        _role_permissions = "";
                    }
                    String[] str_role_permissions = _role_permissions.split(",");
                    for (int i = 0; i < str_role_permissions.length; i++) {
                        if(this.pathMatcher.matches(str_role_permissions[i],requestURI)) {
                            bool_uri = true;
                        }
                    }
                }
                if(bool_uri==false){
                    Map<String, Object> data = new HashMap<>();
                    data.put("code", CodeUtils.PERMISSSION_OUT);
                    servletRequest.setAttribute("data", data);
                    servletRequest.getRequestDispatcher("/actuator/printf").forward(servletRequest, servletResponse);
                    return;
                }
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * @return true 跳出 false 继续验证
     */
    public boolean isExclusion(String requestURI, Set<String> param) {
        if (param == null) {
            return false;
        } else {
            Iterator<String> i$ = param.iterator();
            String pattern;
            do {
                if (!i$.hasNext()) {
                    return false;
                }
                pattern = (String) i$.next();
            } while (!this.pathMatcher.matches(pattern, requestURI));

            return true;
        }
    }

}
